/**
 * Copyright (C), 2011-2016 The Store
 * File Name: EventDispatcher.java
 * Encoding: UTF-8
 * Date: Feb 28, 2012
 * History: 
 */
package com.waynewan.qcomet.event;

import java.util.Date;
import java.util.concurrent.ExecutorService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.waynewan.qcomet.listener.AbstractListener;
import com.waynewan.qcomet.listener.RegisterService;

/**
 *
 * @author Wayne Wan(bestirwiny@gmail.com)
 * @version Revision: 1.00 Date: Feb 28, 2012
 */
public class EventDispatcher {
	private static Log log = LogFactory.getLog(EventDispatcher.class);
	
	private static EventDispatcher dispatcher = null; 
	
	private ExecutorService threadPool;
	
	private EventDispatcher(ExecutorService threadPool){
		this.threadPool = threadPool;
	}
	
	/**
	 * this method is not thread safe
	 * @Title: createInstance
	 * @Description:
	 * @param 
	 * @return EventDispatcher
	 * @author Wayne Wan(waynewan@mail.com)
	 * @date  Feb 29, 2012
	 */
	public static EventDispatcher createInstance(ExecutorService threadPool){
		if(dispatcher==null)
			dispatcher = new EventDispatcher(threadPool);
		return dispatcher;
		
	}
	
	public static EventDispatcher getInstance(){
		if(dispatcher==null) throw new RuntimeException("instance has not been initialized");
		return dispatcher;
	}
	
	/**
	 * the token was used to indicate this destination of this message, 
	 * if null then means this message would be send to all listener who registered on this event 
	 * @param token  
	 * @param event
	 * @param payLoad
	 */
	public void fire(String token, String event, String payLoad){
		if(!RegisterService.isEventListenerExist(event)) 
			throw new RuntimeException("event[" + event + "] listener have not been registered yet");
		log.debug("fire an event : " + event + " with payload : " + payLoad);
		log.debug("current connection size for event " + event + " : " + RegisterService.getEventListener(event).getConnSize());
		GenericEvent evnt = new GenericEvent(token, event, new Date(), payLoad);
		EventFireThread fireThread = new EventFireThread(evnt);
		threadPool.execute(fireThread);
	}
}

class EventFireThread implements Runnable{
	private GenericEvent evnt;
	public EventFireThread(GenericEvent event){
		this.evnt = event;
	}
	
	@Override
	public void run() {
		AbstractListener listener = RegisterService.getEventListener(this.evnt.getEventName());
		listener.updated(this.evnt);
	}
}
